﻿using System;
using System.Collections.Generic;
using System.Text;
using Neonagee.LocalPreferences;
using UnityEngine;
using UnityEngine.Profiling;
using Yoozoo.Core.Common;
using Yoozoo.Gameplay.City;
using Yoozoo.Gameplay.Liberty;
using Yoozoo.Gta.Common;
using Yoozoo.Modules.Update;
using GameHelper = Yoozoo.Modules.Update.GameHelper;

namespace Yoozoo.Mars.Got
{
    /// <summary>
    /// 帧率统计
    /// 画质调整
    /// </summary>
    public partial class DeviceAgent : MonoBehaviour, IDeviceAgent
    {
        private int m_fps;
        private int m_frames;
        private float m_lastInterval;
        private StringBuilder m_fpsGUIStr = null;
        private GUIStyle m_guiStyle = null;
        private Rect m_renderRect;

        private static DeviceAgent _instance;
        FrameTiming[] frameTimings = new FrameTiming[3];
        
        private readonly float UPDATE_INTERVAL = 0.5f;
        private int quietTime;
        private int _currentTargetRate = -1;
        private bool _hasOverrideTargetRate = false;
        public bool HasOverrideTargetRate => _hasOverrideTargetRate;
        private uint m_frameCount;
        
        const uint kNumFrameTimings = 2;
        private double m_gpuFrameTime;
        private double m_cpuFrameTime;
        private int _nfps;
        private int m_sliceFps;
        private int m_avgFps;
        private int m_minFps;

        private long m_totalFrames;
        private float m_totalFrameStartTime;
        private float m_periodFpsStartTime;
        private int m_periodFrames;
        
        private const string DevicesTargetRate = "DevicesTargetRate";

        public static DeviceAgent Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = FindObjectOfType<DeviceAgent>();
                }
                return _instance;
            }
        }
        
        private void Awake()
        {
#if USE_GM_COMMOND
            //注册需响应的事件
            EventSystem.EventDispatch.Instance.AddEvent<object>(EventSystem.EventConst.EVENT_GM_COMMAND, GMCommandSuccess);
#endif
            InitializeNativeKits();

            GetSystemInfo();
            Application.lowMemory += LowMemoryCallback;

            if (!SystemInfo.supportsInstancing)
            {
                Debug.LogError("设备需要支持GpuInstancing");
            }

           // EventSystem.EventDispatch.Instance.AddEvent(EventSystem.EventConst.EXIT_GAME_APP, PopupExitMessage);
        }
//         public void PopupExitMessage()
//         {
//             //游戏退出
//             UIManager.Instance.GetMessageBox().PopMessageBox(
//                 UMT.Framework.TipStrings.Instance.strWarmPrompt, UMT.Framework.TipStrings.Instance.strQuit,
//                 UMT.Framework.TipStrings.Instance.strOk, UMT.Framework.TipStrings.Instance.strCancle,
//                 () =>
//                 {
//                     if (SDKLuaHelper.IsSDKLogin())
//                     {
//                         SDKAgent.Instance.TriggerGameExitAdvertEvent();
//                     }
// #if (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX) && !UNITY_EDITOR
//                     SDKAgent.Instance.NeedQuit = true;
// #endif
//                     Application.Quit();
//                 },
//                 CloseExitMessageBox);
//         }

        private void Start()
        {
            m_guiStyle = new GUIStyle();
            m_guiStyle.fontSize = 30;
            m_guiStyle.normal.textColor = Color.magenta;

            m_renderRect = new Rect(0, 40, 100, 30);

            m_fpsGUIStr = new StringBuilder();

            m_lastInterval = Time.realtimeSinceStartup;

            m_frames = 0;

            m_avgFps = int.MaxValue;
            m_minFps = int.MaxValue;

            //SetTargetFps(TARGET_FPS);
            Application.focusChanged += FocusChangedCallBackFunc;
            m_sliceFps = -1;

            // int minFps = int.MaxValue;
            // foreach (var resolution in Screen.resolutions)
            // {
            //     if (minFps > resolution.refreshRate)
            //     {
            //         minFps = resolution.refreshRate;
            //     }
            // }
            //
            // int minFps = 25;//性能测试标准不能低于25帧
            // if (minFps > TARGET_FPS) minFps = TARGET_FPS;
            //
            // m_sliceFps = minFps;

            _hasOverrideTargetRate = LocalPrefs.HasKey(DevicesTargetRate);
            _currentTargetRate = LocalPrefs.GetInt(DevicesTargetRate, -1);
            
            m_totalFrameStartTime = Time.realtimeSinceStartup;
            m_totalFrames = 0;
            m_periodFpsStartTime = Time.realtimeSinceStartup;
            m_periodFrames = 0;
        }

        private void Update()
        {
//#if DEVELOPMENT_BUILD || UNITY_EDITOR
            CalculateFPS();
//#endif


            // if (TouchWrapper.TouchCount == 0)
            // {
            //     if (quietTime > 2 * _currentTargetRate)
            //     {
            //         //TODO: 原来定的是60帧，现在改成30帧了，这个逻辑也没啥用了
            //         if (_currentTargetRate > 30)
            //         {
            //             AutoChangeFps(30);  
            //         }
            //         else
            //         {
            //             AutoChangeFps(m_sliceFps);
            //         }
            //        
            //     }
            //
            //     quietTime++;
            // }
            // else
            // {
            //     AutoChangeFps(_currentTargetRate);
            //     quietTime = 0;
            // }

            // DetermineResolution();
#if UNITY_ANDROID
            OnAndroidBackspace();
#endif
        }

        private void OnAndroidBackspace()
        {
            if (Input.GetKeyDown(KeyCode.Escape))
            {
                //todo
                Debug.Log("安卓按下了返回键");
            }
        }

        private void CalculateFPS()
        {
            ++m_frames;
            ++m_totalFrames;
            ++m_periodFrames;
            float timeNow = Time.realtimeSinceStartup;
            if (timeNow >= m_lastInterval + UPDATE_INTERVAL)
            {
                m_fps = (int)(m_frames / (timeNow - m_lastInterval));
                m_frames = 0;
                m_lastInterval = timeNow;
            }
            
            if (m_minFps > 60 || m_fps < m_minFps)
                m_minFps = m_fps;

            if (m_avgFps > 60)
                m_avgFps = m_fps;

            var passedTime = timeNow - m_totalFrameStartTime;
            if (passedTime > 0)
            {
                m_avgFps = (int)(m_totalFrames / passedTime);
            }
        }

        private void FocusChangedCallBackFunc(bool hasFocus)
        {
            Debug.LogFormat("Application FocusChanged {0}",hasFocus);
        }
        
        // 估算下一帧时间并在必要时更新分辨率缩放。
        private void DetermineResolution()
        {
            ++m_frameCount;
            if (m_frameCount <= kNumFrameTimings)
            {
                return;
            }
            FrameTimingManager.CaptureFrameTimings();
            FrameTimingManager.GetLatestTimings(kNumFrameTimings, frameTimings);
            if (frameTimings.Length < kNumFrameTimings)
            {
                Debug.LogFormat("Skipping frame {0}, didn't get enough frame timings.",
                    m_frameCount);

                return;
            }
            else
            {
                m_gpuFrameTime = (double) frameTimings[0].gpuFrameTime; 
                m_cpuFrameTime = (double) frameTimings[0].cpuFrameTime;
                Debug.LogFormat("m_gpuFrameTime = {0} m_cpuFrameTime = {1}",m_gpuFrameTime,m_cpuFrameTime);
            }
        }

        public void resetCalulateFps()
        {
            m_minFps = m_fps;
            m_periodFpsStartTime = Time.realtimeSinceStartup;
            m_periodFrames = 0;
        }

        public void SetTargetFps(int targetFps)
        {
            if (targetFps > 0)
            {
                _hasOverrideTargetRate = true;
                _currentTargetRate = targetFps;
                LocalPrefs.SetInt(DevicesTargetRate, targetFps);
            }
        }

        public int getTargetFps()
        {
            if (_hasOverrideTargetRate && _currentTargetRate>0)
            {
                return _currentTargetRate;
            }
            
            if (QualityHelper.FpsLimitQualityListener!=null)
            {
                return QualityHelper.FpsLimitQualityListener.fpsLimit;
            }
            
            #if (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX) && !UNITY_EDITOR
            return 90;
            #else
            return 30;
            #endif
        }

        public int getCurrentFps()
        {
            return m_fps;
        }

        public int getAvgFps()
        {
            return m_avgFps;
        }

        public int getMinFps()
        {
            return m_minFps;
        }

        /// <summary>
        /// 获取设备ID（不可靠）
        /// </summary>
        /// <returns></returns>
        public string GetDeviceId()
        {
            return SystemInfo.deviceUniqueIdentifier;
        }

        public int getPeriodFps()
        {
            var time = Time.realtimeSinceStartup - m_periodFpsStartTime;
            if (time > 0)
            {
                return (int) (m_periodFrames / time);
            }
            return 0;
            
        }

        /// <summary>
        /// 获取设备语言
        /// </summary>
        /// <returns></returns>
        public string GetSystemLang()
        {
            return Application.systemLanguage.ToString();
        }

        public string GetClientTimezone()
        {
            return TimeZoneInfo.Local.DisplayName;
        }
        //记录一下上次的lowmemory时间
        private static float lastForceReleaseTime = 0;

        private static int ForceReleaseStep = 300;

        private static int lowMemoryCount = 0;

        private static bool waitForExit = false;

        /// <summary>
        /// 白名单，有些玩家又充钱又用挫手机，只能给他加个白名单
        /// 点击设置 - 服务条款与隐私政策 - 确定，后自动加入到白名单
        /// </summary>
        private bool isInWhiteList = false;

        public void SetInWhiteList(bool inWhiteList)
        {
            isInWhiteList = inWhiteList;
        }

        //设备低内存警告
        void LowMemoryCallback()
        {
            UnityEngine.Debug.LogWarning("LowMemoryCallback....");
            lowMemoryCount++;
            //这些用户会给差评，服了
            //该退不退，自动退出； 极个别的用户可能会贡献大量的ANR，导致超过平台的阈值，减少曝光
            // if (!isInWhiteList && waitForExit && lowMemoryCount > 3)
            // {
            //     GameHelper.QuitApplication();
            //     return;
            // }
            //

            GetUseMemoryInfo();
           if (!isInWhiteList && (CheckIsANRMode() || lowMemoryCount > 5))
           {
                string memoryState = DeviceInfo.GetMemoryState();
                if (!string.IsNullOrEmpty(memoryState))
                {
                    // states[0], states[1], states[2] 分别是可用内存状态、总内存大小、是否处于低内存状态
                    string[] states = memoryState.Split('|');
                    UnityEngine.Debug.LogWarning(memoryState);
                    ulong availabelMemory = ulong.Parse(states[0]) / 1024 / 1024;
                    ulong totalMemory = ulong.Parse(states[1]) / 1024;
                    if (availabelMemory  < 600 || totalMemory < 3000 ) //提示资源不足
                    {
                        UnityEngine.Debug.LogWarning("LowMemoryCallback...." + DeviceReportInfo.model);
                        ResidentHandler.Inst.GetFunction("G_GameHelper.ShowLowMemoryAlert").Action();
                        return;
                    }
                }
            }

            // //300s内只能调用一次GC  或者 低内存警告次数大于3次可能说明forceRelease无效
            // if (Time.realtimeSinceStartup - lastForceReleaseTime < ForceReleaseStep || lowMemoryCount > 3)
            // {
            //     UnityEngine.Debug.LogWarningFormat("LowMemoryCallback....since:{0}", Time.realtimeSinceStartup);
            //     return;
            // }
            //
            // lastForceReleaseTime = Time.realtimeSinceStartup;
            //通知系统低内存警告，进行内存释放
            //TODO: 清理资源管理器
            // 向lua抛消息
            //BlueprintUtils.ExeEventFunc("LowMemory");
            //调用GC
            //Yoozoo.Gta.Common.GameHelper.ForceRelease();
            // UnityEngine.Debug.LogWarning("LowMemoryCallback....ForceRelease  end");
            // GetUseMemoryInfo();
        }

        // ANR排行榜 TOP5,红米含量100%
        private List<string> m_deviceName = new List<string>
        {
            "M2003J15SC", // Redmi 10X
            "M2004J19C", // Redmi 9 M2004J19C
            "Redmi Note 8",
            "M2010J19SG", // Xiaomi Redmi 9T
            "M2006C3LG", // Redmi 9A M2006C3LG
            "Huawei Y9 Prime", // Huawei Y9 Prime (2019) (STK-LX3) 
            "Poco X5 Pro", // Xiaomi Poco X5 Pro (22101320G)
            "Poco X3 Pro", // 小米 Poco X3 Pro (M2102J20SG)
            "CRT-NX3", // HONOR/CRT-NX3
            "2109119DG", // 小米 11 Lite 5G NE (2109119DG)
        };

        public void SetDeviceNames(string deviceNames)
        {
            if (string.IsNullOrEmpty(deviceNames))
                return;

            var substrings = deviceNames.Split("|");
            foreach (var deviceName in substrings)
            {
                m_deviceName.Add(deviceName.Trim());
            }
        }

        /// <summary>
        /// 监测是否是ANR导致的模型
        /// </summary>
        /// <returns></returns>
        private bool CheckIsANRMode()
        {
            if (string.IsNullOrEmpty(DeviceReportInfo.model))
                return false;
            
            bool isAnrDevice = false;
            foreach (var deviceName in m_deviceName)
            {
                if (DeviceReportInfo.model.Contains(deviceName))
                {
                    isAnrDevice = true;
                    break;
                }
            }

            return isAnrDevice;
        }

        private void GetUseMemoryInfo()
        {
            try
            {
                var AllocatedRam = Profiler.GetTotalAllocatedMemoryLong()/ 1048576f;
                var ReservedRam  = Profiler.GetTotalReservedMemoryLong() / 1048576f;
                var MonoRam      = Profiler.GetMonoUsedSizeLong()        / 1048576f;
                var MonoRRam     = Profiler.GetMonoHeapSizeLong()         / 1048576f;
                var GraphicRam   = Profiler.GetAllocatedMemoryForGraphicsDriver()/1048576f;
                var TextrueRam   = Texture.currentTextureMemory/1048576f;
                var TextrueRamDesired = Texture.desiredTextureMemory/1048576f;
                var TextrueRamTotal = Texture.totalTextureMemory/1048576f;
                var luaRam = Yoozoo.Framework.Managers.LuaManager.mainState.Memory / 1024f;
                var memoryInfo = $"lowMemory: AR: {(int)AllocatedRam}, RR: {(int)ReservedRam}, MR: {(int)MonoRam}, MRR: {(int)MonoRRam}, GR: {(int)GraphicRam}, TRT: {(int)TextrueRamTotal}, LRam: {(int)luaRam}";
                UnityEngine.Debug.Log(memoryInfo);
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError(e);
            }
          
            
        }
        
        private void GetSystemInfo()
        {
            //if (Debug.unityLogger.logEnabled)
            {
                string systemInfo =
                    "UnityVersion->" + Application.unityVersion + " | " +
                    "设备模式->" + SystemInfo.deviceModel + " | " +
                    "图形设备名称->" + SystemInfo.graphicsDeviceName + " | " +
                    "CPU类型->" + SystemInfo.processorType + " | " +
                    "CPU名称->" + DeviceInfo.GetCPUName() + " | " +
                    "CPU核心数->" + SystemInfo.processorCount + " | " +
                    "CPU频率->" + SystemInfo.processorFrequency + " | " +
                    "内存大小->" + DeviceInfo.systemMemorySize + " | " +
                    //"MaxHeap->" + DeviceInfo.GetMaxHeapMemory() + " | " +
                    "显卡设备类型->" + SystemInfo.graphicsDeviceType + " | " +
                    "GPUInstancing->" + SystemInfo.supportsInstancing + " | " +
                    "支持最大图片尺寸->" + SystemInfo.maxTextureSize;
                UnityEngine.Debug.Log(systemInfo);
                UnityEngine.Debug.Log("Application.persistentDataPath->" + Application.persistentDataPath);
                UnityEngine.Debug.Log("Application.streamingAssetsPath->" + Application.streamingAssetsPath);
            }
        }

        /// <summary>
        /// 初始化NativeKits，注册监听
        /// </summary>
        public void InitializeNativeKits()
        {
            DeviceInfo.InitializeNativeKits(name);
        }

        /// <summary>
        /// 安卓，接受到 ACTION_HEADSET_PLUG 事件
        /// </summary>
        /// <param name="state">"1"耳机插入，"0"拔出</param>
        private void onHeadsetPlug(string state)
        {
            Debug.LogFormat("[Audio]onHeadsetPlug: {0}", state);
            DeviceInfo.SetHeadsetPlugState(state);
        }

    }
}
